#include "pch.h"

BuildingSceneContactListener::BuildingSceneContactListener():m_skipSolve(true)
{

}

void BuildingSceneContactListener::PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
{
	if(m_skipSolve)
	{
		contact->SetEnabled(false);
	}
}

void BuildingSceneContactListener::SetSkipSolve(bool flag)
{
	m_skipSolve = flag;
}

BuildingSceneContactListener* BuildingScene::GetContactListener()
{
	return &m_ContactListener;
}

std::shared_ptr<RobotBuilder> BuildingScene::GetRobotBuilder()
{
	return m_RobotBuilder;
}

BuildingScene::BuildingScene():m_BuildRobot(NULL)
{
	m_RobotBuilder = std::shared_ptr<RobotBuilder>(new RobotBuilder);
}

BuildingScene::~BuildingScene()
{
}

void BuildingScene::Initialize()
{
	m_Ground = std::shared_ptr<Ground>(new Ground());
	m_Ground->Initialize();
	DirectX2DRender::Instance()->GetCurrentCamera()->SetPosition(float3(0.f, 13.f, 30.f));

	Box2DManager::Instance()->SetEnableGravrity(false);
}

void BuildingScene::GameStart()
{
	Box2DManager::Instance()->SetEnableGravrity(true);
	m_ContactListener.SetSkipSolve(false);
}

void BuildingScene::GameEnd()
{
	Box2DManager::Instance()->SetEnableGravrity(false);
	m_ContactListener.SetSkipSolve(true);
}

void BuildingScene::OnUpdate(float frameTime)
{
	if(m_Ground)
		m_Ground->OnUpdate(frameTime);

	m_RobotBuilder->OnUpdate(frameTime);
}

void BuildingScene::OnPreRender()
{
	if(m_Ground)
		m_Ground->OnPreRender();

	m_RobotBuilder->OnPreRender();
}

bool BuildingScene::ParseRobot(const char* xml, uint length)
{
	if(!m_BuildRobot)
	{
		m_BuildRobot = RobotManager::Instance()->CreateRobot();

		m_BuildRobot->SetCorePosition(float2(0.f, 15.f));

		tinyxml2::XMLDocument doc;
		tinyxml2::XMLError error = doc.Parse(xml, length);
		if(error != tinyxml2::XML_NO_ERROR)
			return false;

		tinyxml2::XMLHandle docHandle(&doc);
		tinyxml2::XMLElement *robot_node = docHandle.FirstChildElement(XML_ROBOT).ToElement();

		m_BuildRobot->LoadParts(robot_node, false);
		m_BuildRobot->CreateParts();
		m_BuildRobot->CreateJoints();
	}
	else
	{
		m_BuildRobot->Reset();
	}

	m_BuildRobot->Initialize();
	m_BuildRobot->SetActive(true);
	return true;
}

void BuildingScene::SaveRobot2XML()
{
	tinyxml2::XMLDocument doc;
	doc.InsertEndChild(doc.NewDeclaration());
	doc.SetBOM( true );

	tinyxml2::XMLNode* robot_node = doc.InsertEndChild( doc.NewElement(XML_ROBOT));
	m_BuildRobot->SaveAttribute(doc, robot_node);

	tinyxml2::XMLPrinter printer;

	doc.Print(&printer);
	const char* buffer = printer.CStr();
	int length = printer.CStrSize() - 1;

	BasicLoader^ loader = ref new BasicLoader(DirectX2DRender::Instance()->GetDevice().Get());
	Platform::Array<byte>^ data = ref new Platform::Array<byte>(length);
	for (int i = 0; i < length; i++)
	{
		data[i] = buffer[i];
	}

	
 	loader->SaveRawDataLocal("robot2.xml", data);
}

void BuildingScene::GenerateJoint()
{
	b2World* world_ref = Box2DManager::Instance()->GetWorld();
	b2Contact* contact = world_ref->GetContactList();
	uint robot_id = m_BuildRobot->uid;

	JointCreateInfo joint_info;

	while (contact)
	{
		b2Shape::Type typeA = contact->GetFixtureA()->GetType();
		b2Shape::Type typeB = contact->GetFixtureB()->GetType();
		BodyInfo* infoA = static_cast<BodyInfo*>(contact->GetFixtureA()->GetBody()->GetUserData());
		BodyInfo* infoB = static_cast<BodyInfo*>(contact->GetFixtureB()->GetBody()->GetUserData());

		if(!infoA || !infoB)
		{
			contact = contact->GetNext();
			continue;
		}

		RobotPartBase* partA = static_cast<RobotPartBase*>(infoA->owner_point);
		RobotPartBase* partB = static_cast<RobotPartBase*>(infoB->owner_point);
		if(!partA || !partB || partA->owner_id != robot_id || partB->owner_id != robot_id)
		{
			contact = contact->GetNext();
			continue;
		}

		if((typeA == b2Shape::e_circle && typeB == b2Shape::e_circle))
		{
			contact = contact->GetNext();
			continue;
		}

		if(typeA == b2Shape::e_circle)
		{
			joint_info.partA_uid = partA->uid;
			joint_info.partB_uid = partB->uid;
			m_BuildRobot->AddJointsDef(joint_info);
		}
		else if(typeB == b2Shape::e_circle)
		{
			joint_info.partB_uid = partA->uid;
			joint_info.partA_uid = partB->uid;
			m_BuildRobot->AddJointsDef(joint_info);
		}
		else
		{
			joint_info.partA_uid = partA->uid;
			joint_info.partB_uid = partB->uid;
			m_BuildRobot->AddJointsDef(joint_info);

			joint_info.partB_uid = partA->uid;
			joint_info.partA_uid = partB->uid;
			m_BuildRobot->AddJointsDef(joint_info);
		}

		contact = contact->GetNext();
	}
	m_BuildRobot->CreateJoints();
}


